home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS26.ADF
/
SoundScape
/
AztecExamples
/
vu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-26
|
8KB
|
290 lines
/* VU.C VU Meter for the Sampler
(c) 1987 Todor Fay
AZTEC C version
*/
#include "exec/exec.h"
#include "exec/types.h"
#include "soundscape.h"
#include "intuition/intuition.h"
/* Images for the LEDs. A red LED for lighting,
a blue LED for turning it back off
(the background color.)
*/
UWORD redleddata[] = { /* 16 x 3 */
65535,
65535,
65535,
65535,
65535,
65535,
};
struct Image redledimage = { 0,0,16,3,2,redleddata,3,0,0 };
UWORD blueleddata[] = { /* 16 x 3 */
0,
0,
0,
0,
0,
0,
};
struct Image blueledimage = { 0,0,16,3,2,blueleddata,3,0,0 };
/* We don't need any Intuition Gadgets, just a
window to display the LEDs in.
This was designed with Power Windows.
*/
struct NewWindow NewWindowStructure = {
0,0,
250,20,
0,1,
NULL,
WINDOWDRAG+WINDOWDEPTH,
NULL,
NULL,
"VU Meter",
NULL,
NULL,
5,5,
0,0,
WBENCHSCREEN
};
short thisport; /* This port's id. */
long SoundScapeBase; /* SoundScape library. */
long IntuitionBase;
/* We need a place to store the Sampler's
output routine address, since we are replacing
the code pointer in its port structure
with our own.
*/
void (*sampleroutcode) ();
struct Window *vuwindow; /* Display window. */
/* We need an array of velocity values for each
note that is being played. These are zeroed
for no note.
If you add up all the velocities in this
array, you should get totalvolume, which
is used to determine the number of LEDs to
light.
*/
unsigned char velocity[128];
unsigned short totalvolume;
insertoutcode(note)
/* This output routine is not given to the Patch
Panel in the AddMidiPort call. Instead, this
routine replaces the Sampler output code, and
then calls it. So, this is inserted there by
the open routine.
Check the note status. If it is NOTEON or NOTEOFF,
we want to use it for the display.
Start by decrementing the totalvolume by
velocity[note->value]. If this is a NOTEOFF
event, this reduces totalvolume appropriately.
If this is a NOTEON event, this clears any
previous NOTEON that was stored. This is
neccessary because we aren't supporting multiple
playing of the same note (for simplicity.)
If this is a NOTEON event, increment totalvolume
by the velocity of this note. Store this
velocity in the velocity array.
Else, for a NOTEOFF event, simply put zero in
the velocity array - there is no note being
played.
Compute how many LEDs should be on from
totalvolume. Each additional LED represents
a doubling in volume, so figure what the most
significant bit of totalvolume is.
If the new top LED position (newvupos) is
greater than the currently displayed one
(vupos), draw in the extra LEDs. Else,
if newvupos is less than vupos, erase
LEDs down to newvupos.
Finally, forward the note event to the
Sampler by calling its output routine.
*/
struct Note *note;
{
unsigned char status = note->status & 0xF0;
static short vupos = 0;
short newvupos, index;
if (sampleroutcode) {
if ((status == NOTEON) || (status == NOTEOFF)) {
totalvolume -= velocity[note->value];
if ((status == NOTEON) && note->velocity) {
totalvolume += note->velocity;
velocity[note->value] = note->velocity;
}
else velocity[note->value] = 0;
newvupos = 0;
index = 4;
for (;index < totalvolume; index = index << 1)
newvupos++;
if (newvupos < vupos) {
for (;vupos > newvupos; vupos--)
DrawImage(vuwindow->RPort,
&blueledimage,-10 + vupos * 20,13);
}
else if (newvupos > vupos) {
vupos++;
for (;vupos <= newvupos; vupos++)
DrawImage(vuwindow->RPort,
&redledimage,-10 + vupos * 20,13);
}
vupos = newvupos;
}
(*sampleroutcode) (note);
}
else FreeNode(note);
}
outcode(note)
/* This, the outcode for this module, does
nothing.
*/
struct Note *note;
{
enteraztec();
FreeNode(note);
leaveaztec();
}
opencode(direction)
/* This installs the VU meter.
If this is to install the output routine:
Get the Port structure for the Sampler.
If the Sampler already has its output
code stolen, (samplerport->show has somebody's
port id) do nothing. Else, open the window,
give samplerport->outcode insertoutcode
and put the Sampler's output code
in samplercode. Set samplerport->show to
this port's id, so no other module will
monkey with it.
*/
char direction;
{
short i;
struct Port *samplerport;
enteraztec();
if (!direction) {
samplerport = (struct Port *)
MidiPort(FindMidiPort("sampler"));
if (samplerport) {
if (samplerport->show) {
CloseMidiPort(samplerport->show,0);
}
if (!samplerport->show) {
vuwindow = (struct Window *)
OpenWindow(&NewWindowStructure);
if (vuwindow) {
totalvolume = 0;
for (i=0; i < 128; i++)
velocity[i] = 0;
sampleroutcode = samplerport->outcode;
samplerport->outcode = insertoutcode;
samplerport->show = thisport;
leaveaztec();
return(1);
}
}
}
}
leaveaztec();
return(0);
}
closecode(direction)
/* This deactivates the VU Meter.
Simply return the Sampler's output routine
to its Port structure and clear
samplerport->show. Close the display
window.
*/
{
struct Port *samplerport;
enteraztec();
if (!direction) {
samplerport = (struct Port *)
MidiPort(FindMidiPort("sampler"));
if (samplerport && sampleroutcode) {
samplerport->outcode = sampleroutcode;
samplerport->show = 0;
}
if (vuwindow) CloseWindow(vuwindow);
vuwindow = 0;
}
leaveaztec();
return(1);
}
/* The main program is standard with one addition:
After installing this port, call OpenMidiPort
to activate it. This is needed because there
is no icon for the user to click on. We
could have added that icon, but it would be
one more item on the Patch Panel, cluttering
it and causing some confusion since nothing
can be sent directly to it.
There is a chance OpenMidiPort will fail. This
is because the Sampler's output routine was
already stolen. If so, there is no need to
stick around, so call RemoveMidiPort and leave.
Normally, RemoveMidiPort is done by SoundScape
when it closes down, but this time we'll
do it ourselves to get out early.
*/
main() {
IntuitionBase = OpenLibrary("intuition.library",0);
SoundScapeBase = OpenLibrary("soundscape.library",0);
if (SoundScapeBase) {
CloseLibrary(SoundScapeBase);
thisport = AddMidiPort(opencode,closecode,0,
outcode,0,0,-1,"vu meter");
if (OpenMidiPort(thisport,0)) {
SetTaskPri(FindTask(0),-20);
while (MidiPort(thisport)) Delay(100);
}
else RemoveMidiPort(thisport);
}
CloseLibrary(IntuitionBase);
}